<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace app\admin\helper;

final class Form
{
    private static $csrf_hidden_name = '_ft';
    private static $controls_hidden_name = '_fc';

    public function render_csrf_token($key = '')
    {
        return $this->render_hidden($this->$csrf_hidden_name, Csrf::generate($key));
    }

    public function handle_post()
    {
        $post = request()->post();
        $data = array();

        foreach (array_keys($post) as $name) {
            if (substr($name, 0, 1) != '_') {
                $data[$name] = $post[$name];
            }
        }

        if (isset($post[self::$controls_hidden_name])) {
            foreach ((array) $post[self::$controls_hidden_name] as $name) {
                $this->_ensure_exists($data, $name);
            }
        }

        return $data;
    }

    private function _ensure_exists(&$array, $name)
    {
        if (($pos = strpos($name, '[')) !== false) {
            $items = explode('|', str_replace(array('][', '['), '|', trim($name, '[]')));

            for ($i = 0; $i < count($items) - 1; $i++) {
                if (!array_key_exists($items[$i], $array)) {
                    $array[$items[$i]] = array();
                }
                $array =& $array[$items[$i]];
            }

            if (!array_key_exists($items[$i], $array)) {
                $array[$items[$i]] = '';
            }



//             $first = substr($name, 0, $pos);
//             if (!array_key_exists($first, $array)) {
//                 $array[$first] = array();
//             }

//             //$rpos = strpos($name, ']', $pos + 1);

//             $child = trim(substr($name, $pos), '[]');
//             if ($child) {
//                 $this->_ensure_exists($array[$first], $child);
//             }
        } else {
            if (!array_key_exists($name, $array)) {
                $array[$name] = '';
            }
        }
    }

    public function render_group($name, $value, $control, $label, $help = null, $options = array())
    {
        $control_html = $this->render_control($name, $value, $control, $label, $help, $options);
        return helper('admin/html')->render_tag('div', array('class' => 'form-group'), $control_html);
    }

    public function render_control($name, $value, $control, $label, $help = null, $options = array())
    {
        $label_html = $this->render_label($label, array('for' => $name));
        $help_html = $help ? $this->render_help($help) : null;

        $control_method = 'render_' . $control;
        $control_html = $this->$control_method($name, $value, $options);

        $hidden_html = $this->render_hidden(self::$controls_hidden_name . '[]', $name);
        return $label_html . $control_html . $help_html . $hidden_html;
    }

    public function render_label($label, $options = array())
    {
        $attributes['class'] = 'control-label';
        $attributes = array_merge($attributes, $options);
        return helper('admin/html')->render_tag('label', $attributes, $label . '：&nbsp;');
    }

    public function render_help($help, $options = array())
    {
        $attributes['class'] = 'help-block';
        $attributes = array_merge($attributes, $options);
        return helper('admin/html')->render_tag('span', $attributes, $help);
    }

    public function render_button($text, $icon, $class, $options = array())
    {
        $icon_html = $icon ? helper('admin/html')->render_tag('i', array('class' => $icon)) : null;

        $attributes['type'] = 'button';
        $attributes['class'] = $class;
        $attributes = array_merge($attributes, $options);
        return helper('admin/html')->render_tag('button', $attributes, $icon_html . '&nbsp;&nbsp;' . $text . '&nbsp;&nbsp;');
    }

    public function render_submit_and_cancel($submit_url, $cancel_url)
    {
        $submit_html = $this->render_button('确定', null, 'btn btn-primary btn-submit ajax-post require-validate loading-icon', array('url' => $submit_url));
        $cancel_html = $this->render_button('取消', null, 'btn btn-default btn-cancel redirect', array('url' => $cancel_url));
        return helper('admin/html')->render_tag('div', array('class' => 'form-group form-actions'), $submit_html . '&nbsp;' . $cancel_html);
    }

    private function _render_input($type, $name, $value, $attributes = array())
    {
        $attributes['type'] = $type;
        !empty($name) && $attributes['name'] = $name;
        $value !== null && $attributes['value'] = $value;
        return helper('admin/html')->render_tag('input', $attributes);
    }

    public function render_hidden($name, $value, $options = array())
    {
        return $this->_render_input('hidden', $name, $value, $options);
    }

    private function _format_cid($name)
    {
        return str_replace(array('[', ']'), '_', $name);
    }

    public function render_text($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('text', $name, $value, $attributes);
    }

    public function render_password($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('password', $name, $value, $attributes);
    }

    public function render_url($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('url', $name, $value, $attributes);
    }

    public function render_email($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('email',$name, $value, $attributes);
    }

    public function render_decimal($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control format format-decimal';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('text', $name, $value, $attributes);
    }

    public function render_number($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control format format-number';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('text', $name, $value, $attributes);
    }

    public function render_textarea($name, $value, $options = array())
    {
        $attributes['name'] = $name;
        $attributes['class'] = 'form-control';
        $attributes['rows'] = 10;
        $attributes = array_merge($attributes, $options);
        return helper('admin/html')->render_tag('textarea', $attributes, $value);
    }

    public function render_switch($name, $value, $options = array())
    {
        $attributes['type'] = 'checkbox';
        $attributes['switch-ref'] = $name;
        $value && $attributes['checked'] = 'checked';
        $attributes = array_merge($attributes, $options);
        $input_html = helper('admin/html')->render_tag('input', $attributes);
        $hidden_html = $this->render_hidden($name, $value);
        return helper('admin/html')->render_tag('div', array('class' => 'sf-switch'), $input_html) . $hidden_html;
    }

    public function render_status($name, $value, $options = array())
    {
        return $this->render_switch($name, $value, $options);
    }

    public function render_date($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes['control'] = 'datetime-picker';
        $attributes['data-format'] = config('SYS_DATE_FORMAT');
        $attributes['value'] = $value;
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('text', $name, $value, $attributes);
    }

    public function render_date_ts($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes['control'] = 'datetime-picker';
        $attributes['ref-hidden'] = $this->_format_cid($name);
        $attributes['data-format'] = config('SYS_DATE_FORMAT');
        $attributes['value'] = sf_format_date($value);
        $attributes = array_merge($attributes, $options);
        $input_html = helper('admin/html')->render_tag('input', $attributes);
        $hidden_html = $this->render_hidden($name, $value, array('hidden-id' => $this->_format_cid($name)));
        return $input_html . $hidden_html;
    }

    public function render_html($name, $value, $options = array())
    {
        $attributes['control'] = 'summernote';
        $attributes['ref-hidden'] = $this->_format_cid($name);
        $attributes['data-height'] = '300';
        $attributes = array_merge($attributes, $options);
        $div_html = helper('admin/html')->render_tag('div', $attributes, $value);
        $hidden_html = $this->render_hidden($name, $value, array('hidden-id' => $this->_format_cid($name)));
        return $div_html . $hidden_html;
    }

    public function render_image($name, $value, $options = array())
    {
        //$options['data-preview-file-type'] = 'image';
        //$options['data-allowed-file-types'] = 'image';
        //$options['data-allowed-file-extensions'] = 'gif';
        return $this->render_file($name, $value, $options);
    }

    public function render_file($name, $value, $options = array())
    {
        $attributes['type'] = 'file';
        $attributes['control'] = 'bootstrap-fileinput';
        $attributes['ref-hidden'] = $this->_format_cid($name);
        $attributes['data-max-file-count'] = 1;
        list($file_ids, $file_list) = $this->_getFileList($value);
        $attributes['initial-file-list'] = $file_list;
        $attributes = array_merge($attributes, $options);
        $input_html = helper('admin/html')->render_tag('input', $attributes);
        $hidden_html = $this->render_hidden($name, $file_ids, array('hidden-id' => $this->_format_cid($name)));
        return $input_html . $hidden_html;
    }

    private function _getFileList($value)
    {
        $file_list = array();
        $file_ids = array();
        foreach (explode(',', $value) as $file_id) {
            $file_info = model('admin/upload')->getFileInfo($file_id);
            if ($file_info) {
                $file_ids[] = $file_info['id'];
                $file_list[] = implode(',', array($file_info['id'], $file_info['name'], $file_info['size'], $file_info['url']));
            }
        }
        return array(implode(',', $file_ids), implode(';', $file_list));
    }

    public function render_select($name, $value, $options = array())
    {
        $params = $this->_parse_params($options, ['list', 'key_field', 'title_field']);
        $list_from = is_string($params['list']) ? helper('admin/options')->parse($params['list']) : (array) $params['list'];
        $key_field = $params['key_field'] ?: 'id';
        $title_field = $params['title_field'] ?: 'title';

//         if (isset($options['list'])) {
//             $list = $options['list'];
//             unset($options['list']);

//             if (is_string($list)) {
//                 $list = helper('admin/options')->parse($list);
//             }
//         } else {
//             $list = array();
//         }

        $list_data = array();

        foreach ($list_from as $i => $data) {
            if ($data instanceof \think\Model) {
                $data = $data->getData();
            }

            if (is_array($data)) {
                $key_value = isset($data[$key_field]) ? $data[$key_field] : $i;
                $title_value = isset($data[$title_field]) ? $data[$title_field] : '';
                $list_data[$key_value] = $title_value;
            } else {
                $list_data[$i] = $data;
            }
        }

        $attributes['name'] = $name;
        $attributes['class'] = 'form-control';
        $attributes['placeholder'] = '请选择';
        $attributes['control'] = 'select2';
        $attributes = array_merge($attributes, $options);
        $html = helper('admin/html')->render_start_tag('select', $attributes);
        //$html .= $this->_render_option($value, '0', '');
        $html .= helper('admin/html')->render_tag('option');

        foreach (array_keys($list_data) as $key) {
            $html .= $this->_render_option($value, $key, $list_data[$key]);
        }

        $html .= helper('admin/html')->render_end_tag('select');
        return $html;
    }

    private function _render_option($select_value, $opt_key, $opt_label)
    {
        $attributes['value'] = $opt_key;
        if ($select_value == $opt_key) {
            $attributes['selected '] = 'selected ';
        }
        return helper('admin/html')->render_tag('option', $attributes, $opt_label);
    }

    public function render_checklist($name, $value, $options = array())
    {
        if (isset($options['list'])) {
            $list = (array) $options['list'];
            unset($options['list']);
        } else {
            $list = array();
        }

        $attributes['class'] = 'checklist-control';
        $attributes = array_merge($attributes, $options);
        $html = helper('admin/html')->render_start_tag('div', $attributes);
        $html .= helper('admin/html')->render_start_tag('div', array('class' => 'checklist-box'));

        foreach (array_keys($list) as $key) {
            $html .= helper('admin/html')->render_start_tag('div', ['class' => 'checkbox']);
            $html .= helper('admin/html')->render_start_tag('label');
            $checked = in_array($key, $list);
            $html .= $this->_render_input('checkbox', $name . '[]', $key, in_array($key, (array) $value) ? array('checked' => 'checked') : null);
            $html .= $list[$key];
            $html .= helper('admin/html')->render_end_tag('label');
            $html .= helper('admin/html')->render_end_tag('div');
        }

        $html .= helper('admin/html')->render_end_tag('div');

        $html .= helper('admin/html')->render_start_tag('div', array('class' => 'checklist-actions'));
        $html .= helper('admin/html')->render_button('选择全部', null, 'btn btn-link select-all');
        $html .= ' / ';
        $html .= helper('admin/html')->render_button('取消选择', null, 'btn btn-link unselect-all');
        $html .= helper('admin/html')->render_end_tag('div');

        $html .= helper('admin/html')->render_end_tag('div');
        return $html;
    }

    private function _parse_params(&$options, $name_list = array())
    {
        foreach ($name_list as $name) {
            if (isset($options[$name])) {
                $value = $options[$name];
                unset($options[$name]);
            } else {
                $value = null;
            }
            $result[$name] = $value;
        }
        return $result;
    }
}